package com.example.lots_of_demo.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Map;

/**
 * @author : LZJ
 * @description : code for LZJ
 * @date : 2021/2/13
 */
@Component
public class JWTUtils {

    @Value("${jwt.secret}")
    private String secret;
    @Value("${jwt.expireHours}")
    private String expireHours;

    /**
     * 根据负责生成JWT的token
     */
    public String generateToken(Map<String, Object> claims, String sub) {
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(sub)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    /**
     * 生成jwt token令牌过期的时间
     */
    private Date generateExpirationDate() {
        LocalDateTime localDateTime = LocalDateTime.now().plusHours(Long.parseLong(expireHours));
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 从token中获取登录用户名
     */
    public String getUserNameFromToken(String token) {
        String username;
        try {
            Claims claims = getClaimsFromToken(token);
            username =  claims.getSubject();
        } catch (Exception e) {
            username = null;
        }
        return username;
    }

    /**
     * 从token中获取Claims对象
     */
    private Claims getClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 判断jwt token是否过期
     */
    private boolean isTokenExpired(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token).getBody().getExpiration().before(new Date());
    }

    /**
     * 验证token是否还有效
     *
     * @param token       客户端传入的token
     * @param userDetails 从数据库中查询出来的用户信息
     */
    public boolean validateToken(String token, UserDetails userDetails) {
        String username = getUserNameFromToken(token);
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }

    /**
     * 根据关键字从jwt token获取值 (键-String  ,  值-String)
     */
    public String getValueFromTokenByKey(String token, String key){
        String value;
        try {
            Claims claims = getClaimsFromToken(token);
            value = (String) claims.get(key);
        } catch (Exception e) {
            value = null;
        }
        return value;
    }

    /**
     * 根据关键字从jwt token获取值 (键-String  ,  值-Object)
     */
    public <T>T getValueFromTokenByKey(String token, String key, Class<T> classz){
        T value;
        try {
            Claims claims = getClaimsFromToken(token);
            value = (T)claims.get(key);

        } catch (Exception e) {
            value = null;
        }
        return value;
    }

}
